<?php

/*
 * This file is part of the Dektrium project
 *
 * (c) Dektrium project <http://github.com/dektrium>
 *
 * For the full copyright and license information, please view the LICENSE.md
 * file that was distributed with this source code.
 */

namespace yiike\user\clients;

use Yii;
use yii\authclient\OAuth2;

/**
 * @author Dmitry Erofeev <dmeroff@gmail.com>
 */
class Qq extends OAuth2 implements \dektrium\user\clients\ClientInterface {

    public $access_token;
    public $openid;
    public $wid;

    /**
     * @inheritdoc
     */
    public $authUrl = 'https://graph.qq.com/oauth2.0/authorize';

    /**
     * @inheritdoc
     */
    public $tokenUrl = 'https://graph.qq.com/oauth2.0/token';

    /**
     * @inheritdoc
     */
    public $apiBaseUrl = 'https://graph.qq.com';

    /**
     * @inheritdoc
     */
    public function init() {
        parent::init();
    }

    /** @inheritdoc */
    public function getEmail() {
        return isset($this->getUserAttributes()['email']) ? $this->getUserAttributes()['email'] : null;
    }

    /** @inheritdoc */
    public function getUsername() {
        return isset($this->getUserAttributes()['username']) ? $this->getUserAttributes()['username'] : null;
    }

    /**
     * @inheritdoc
     */
    protected function defaultNormalizeUserAttributeMap() {
        return [
            'id' => 'openid',
            'username' => 'username',
            'email' => 'email',
            'name' => 'nickname',
            'avatar' => 'figureurl_qq_2',
        ];
    }

    /**
     * @inheritdoc
     */
    public function buildAuthUrl(array $params = []) {
        $authState = $this->generateAuthState();
        $this->setState('authState', $authState);
        $params['state'] = $authState;
        $params['appid'] = $this->clientId;
        return parent::buildAuthUrl($params);
    }

    /**
     * @inheritdoc
     */
    public function getAccessToken() {
        $params = ['access_token' => $this->access_token, 'openid' => $this->openid, 'expires_in' => 7200];
        $config = [ 'class' => \yii\authclient\OAuthToken::className(), 'tokenParamKey' => 'access_token', 'params' => $params];
        $token = Yii::createObject($config);
        $this->setAccessToken($token);
        return $token;
    }

    /**
     * @inheritdoc
     */
    protected function apiInternal($accessToken, $url, $method, array $params, array $headers) {
        $params['access_token'] = $accessToken->getToken();
        $params['openid'] = $accessToken->getParam('openid');
        $params['oauth_consumer_key'] = $this->clientId;
        $req = $this->sendRequest($method, $url, $params, $headers);
        if (isset($req['ret']) && $req['ret'] == 0) {
            $username = md5('qq-' . $this->openid);
            $req['username'] = $username;
            $req['email'] = $username . '@yii.com';
            $req['openid'] = $this->openid;
            return $req;
        } else {
            throw new \yii\base\Exception('Access token is error', 100038);
        }
    }

    /**
     * @inheritdoc
     */
    protected function initUserAttributes() {
        $params['access_token'] = $this->access_token;
        $params['openid'] = $this->openid;
        $params['oauth_consumer_key'] = $this->clientId;
        $data = $this->api('user/get_user_info', 'GET', $params);
        if ($data['ret'] == 0) {
            $username = md5('qq-' . $this->openid);
            $data['id'] = $this->openid;
            $data['username'] = $username;
            $data['email'] = $username . '@yii.com';
            $data['openid'] = $this->openid;
            $data['avatar'] = $data['figureurl_qq_2'];
            return $data;
        } else {
            throw new \yii\base\Exception('Access token is error', 100038);
        }
    }

    /**
     * @inheritdoc
     */
    protected function processResponse($rawResponse, $contentType = self::CONTENT_TYPE_AUTO) {
        if ($contentType === self::CONTENT_TYPE_AUTO && strpos($rawResponse, "callback(") === 0) {
            $count = 0;
            $jsonData = preg_replace('/^callback\(\s*(\\{.*\\})\s*\);$/is', '\1', $rawResponse, 1, $count);
            if ($count === 1) {
                $rawResponse = $jsonData;
                $contentType = self::CONTENT_TYPE_JSON;
            }
        }
        return parent::processResponse($rawResponse, $contentType);
    }

    /**
     * Generates the auth state value.
     * @return string auth state value.
     */
    protected function generateAuthState() {
        return sha1(uniqid(get_class($this), true));
    }

    /**
     * @inheritdoc
     */
    protected function defaultReturnUrl() {
        $params = $_GET;
        unset($params['code']);
        unset($params['state']);
        $params[0] = Yii::$app->controller->getRoute();

        return Yii::$app->getUrlManager()->createAbsoluteUrl($params);
    }

    /**
     * @inheritdoc
     */
    protected function defaultName() {
        return 'qq';
    }

    /**
     * @inheritdoc
     */
    protected function defaultTitle() {
        return 'qq';
    }

    /**
     * @inheritdoc
     */
    protected function defaultViewOptions() {
        return [
            'popupWidth' => 800,
            'popupHeight' => 500,
        ];
    }

}
